package com.godpaper.the5elements.busniess.managers
{
	import com.godpaper.the5elements.model.BoardModel;
	import com.godpaper.the5elements.model.PiecesModel;
	import com.godpaper.the5elements.model.PlayerModel;
	import com.godpaper.the5elements.util.DebugUtil;
	import com.godpaper.the5elements.util.PositionTransactUtil;
	import com.godpaper.the5elements.views.components.GasketButton;
	import com.godpaper.the5elements.views.components.PieceButton;
	import com.godpaper.the5elements.vo.PieceVO;
	
	import de.polygonal.ds.Array2;
	
	import flash.geom.Point;
	
	import jp.dip.hael.gameai.graph.Node;
	import jp.dip.hael.gameai.graph.WeightedEdge;
	
	import mx.collections.ArrayCollection;
	import mx.logging.ILogger;
	import mx.logging.Log;

	/**
	 * 
	 * Manage Pieces' behavior
	 * 
	 */	
	public class PiecesManager
	{
		private static const log:ILogger = Log.getLogger("PiecesManager");
		
		public function PiecesManager()
		{
		}
		
		/**
		 * 
		 * @param nameFilter for simulating pieceButtons such as ToggleButtonBar;
		 * 
		 */		
		public function untoggleOtherPieces(nameFilter:String):void
		{
			var myPieceButton:PieceButton; 
			for(var i:int=0;i<PiecesModel.getInstance().bluePiecesCollection.length;i++)
			{
				myPieceButton = PiecesModel.getInstance().bluePiecesCollection.getItemAt(i) as PieceButton; 
				if(myPieceButton.pieceVO.name!=nameFilter)
				{
					myPieceButton.selected = false;
				}
			}
		}
		/**
		 * 
		 * @param current selected gasketbutton's position
		 * 
		 */		
		public function untoggleOtherGaskets(currentPosition:Array):void
		{
			//reset walkableGBs
			BoardModel.getInstance().walkableGBindexs.removeAll();
			//
			var counter:int = 0;//counter the number of enabled gasketButtons.
			//first off: untoggle other gasketbuttons;
			for(var i:int=0;i<PiecesModel.getInstance().gasketCollection.length;i++)
			{
				if(BoardModel.getInstance().gamePosition.gett( PositionTransactUtil.transactIndex2Array(i)[0],
															   PositionTransactUtil.transactIndex2Array(i)[1] )==null)
				   {
						(PiecesModel.getInstance().gasketCollection.getItemAt(i)  as GasketButton).enabled = 
						 PositionTransactUtil.doseEnabledGBsIsWalkable( BoardModel.getInstance().gasketsPosition.gett( currentPosition[0],
																													   currentPosition[1]) as GasketButton,
																			(PiecesModel.getInstance().gasketCollection.getItemAt(i)  as GasketButton));
						if( (PiecesModel.getInstance().gasketCollection.getItemAt(i)  as GasketButton).enabled == true)
						{
							counter++;
						}													
				   }else
				   {
				   		(PiecesModel.getInstance().gasketCollection.getItemAt(i)  as GasketButton).enabled = false;
				   }										   
			}
			//next calculate addressablePos;
			//at least of 3 enabled gasketButtons  to make up the5elements.
			if(counter>=3)
			{
				var foundFireGBs:ArrayCollection = PositionTransactUtil.doesWalkableGBsIsLinkable(BoardModel.getInstance().walkableGBindexs);
				if(foundFireGBs.length>0)
				{
					BoardManager.triggleAddressableEarthPosition(foundFireGBs);
				}
			}
		}
		
		/**
		 * 
		 * @param target(PieceButton)
		 * @param newDestination
		 * @param newPosition
		 * @return movement result
		 * 
		 */		
		public static function tryMovement(target:PieceButton,newDestination:Point,newPosition:Array):Boolean
		{
			log.info("tryMovement()");
			//trace("target name: ",target.pieceVO.name,"destination original point: ",destination.x,destination.y);
			//refresh gamePosition
			log.debug("target name@tryMovement:{0}",BoardModel.getInstance().gamePosition.gett(target.pieceVO.position[0],target.pieceVO.position[1]).pieceVO.name);
			log.debug("target original position@tryMovement:{0}",target.pieceVO.position[0],target.pieceVO.position[1]);
			
			log.debug("before movement@tryMovement:{0}",BoardModel.getInstance().gamePosition.dump());
			BoardModel.getInstance().gamePosition.sett(target.pieceVO.position[0],target.pieceVO.position[1],null);
			//refresh gameGraph
			var bGBnodeIndex:int = PositionTransactUtil.transactArray2Index(target.pieceVO.position);
			log.debug("current bGBnodeIndex@tryMovement:{0}",bGBnodeIndex);
			var bLeftGB:GasketButton = BoardModel.getInstance().gasketsPosition.gett(target.pieceVO.position[0]-1,target.pieceVO.position[1]) as GasketButton;
			var bTopGB:GasketButton = BoardModel.getInstance().gasketsPosition.gett(target.pieceVO.position[0],target.pieceVO.position[1]-1) as GasketButton;
			var bRightGB:GasketButton = BoardModel.getInstance().gasketsPosition.gett(target.pieceVO.position[0]+1,target.pieceVO.position[1]) as GasketButton;
			var bBottomGB:GasketButton = BoardModel.getInstance().gasketsPosition.gett(target.pieceVO.position[0],target.pieceVO.position[1]+1) as GasketButton;
			
			log.debug("current bLeftGB@tryMovement:{0}",bLeftGB);
			log.debug("current bTopGB@tryMovement:{0}",bTopGB);
			log.debug("current bRightGB@tryMovement:{0}",bRightGB);
			log.debug("current bBottomGB@tryMovement:{0}",bBottomGB);
			//reset graphNode;
			BoardModel.getInstance().gameGraph.removeNode( bGBnodeIndex );
			BoardModel.getInstance().gameGraph.addNode( new Node( bGBnodeIndex ));
			//refresh graphEdge;
			//left
			if( bLeftGB is GasketButton)
			{
				BoardModel.getInstance().gameGraph.addEdge( new WeightedEdge( 
																				PositionTransactUtil.transactArray2Index(bLeftGB.position),
																				bGBnodeIndex,
																				1
																			)
														   );
				if( BoardModel.getInstance().gamePosition.gett(bLeftGB.position[0],bLeftGB.position[1])==null )
				{
					BoardModel.getInstance().gameGraph.addEdge( new WeightedEdge( 
																					bGBnodeIndex,
																					PositionTransactUtil.transactArray2Index(bLeftGB.position),
																					1
																				)
														   );
				}
			}
			//top
			if( bTopGB is GasketButton)
			{
				BoardModel.getInstance().gameGraph.addEdge( new WeightedEdge( 
																				PositionTransactUtil.transactArray2Index(bTopGB.position),
																				bGBnodeIndex,
																				1
																			)
														   );
				if( BoardModel.getInstance().gamePosition.gett(bTopGB.position[0],bTopGB.position[1])==null )
				{
					BoardModel.getInstance().gameGraph.addEdge( new WeightedEdge( 
																					bGBnodeIndex,
																					PositionTransactUtil.transactArray2Index(bTopGB.position),
																					1
																				)
														   );
				}
			}
			//right
			if( bRightGB is GasketButton)
			{
				BoardModel.getInstance().gameGraph.addEdge( new WeightedEdge( 
																				PositionTransactUtil.transactArray2Index(bRightGB.position),
																				bGBnodeIndex,
																				1
																			)
														   );
				if( BoardModel.getInstance().gamePosition.gett(bRightGB.position[0],bRightGB.position[1])==null )
				{
					BoardModel.getInstance().gameGraph.addEdge( new WeightedEdge( 
																					bGBnodeIndex,
																					PositionTransactUtil.transactArray2Index(bRightGB.position),
																					1
																				)
														   );
				}
			}
			//bottom
			if( bBottomGB is GasketButton)
			{
				BoardModel.getInstance().gameGraph.addEdge( new WeightedEdge( 
																				PositionTransactUtil.transactArray2Index(bBottomGB.position),
																				bGBnodeIndex,
																				1
																			)
														   );
				if( BoardModel.getInstance().gamePosition.gett(bBottomGB.position[0],bBottomGB.position[1])==null )
				{
					BoardModel.getInstance().gameGraph.addEdge( new WeightedEdge( 
																					bGBnodeIndex,
																					PositionTransactUtil.transactArray2Index(bBottomGB.position),
																					1
																				)
														   );
				}
			}	
			log.debug("beforeMovement gameGraph status:{0}",DebugUtil.dumpGameGraph());									
															
			//check whether the newPosition has been taken by current postiveSide of selected pieceButton(who)willBeKilled.
			var beTakenPB:PieceButton  = 
					BoardModel.getInstance().gamePosition.gett(newPosition[0],newPosition[1]) as PieceButton;
			if(beTakenPB!=null)
			{
				var beKilledPieceVO:PieceVO = new PieceVO( true,
														   beTakenPB.pieceVO.name,
														   beTakenPB.pieceVO.position );
				
				if(PlayerModel.getInstance().IS_BLUE_TURN_NOW)
				{
					if(beTakenPB.name.indexOf(PieceButton.NAME_PREFIX_RED)!=-1)
					{
						beTakenPB.pieceVO = beKilledPieceVO;
					}	
				}else
				{
					if(beTakenPB.name.indexOf(PieceButton.NAME_PREFIX_BLUE)!=-1)
					{
						beTakenPB.pieceVO = beKilledPieceVO;
					}
				}
			}
		
			//target movement;
			target.move( newDestination.x,newDestination.y);
			//			trace("target new point: ",Application.application.localToGlobal(new Point(target.x,target.y)).toString());
			log.debug("target new position@tryMovement:{0}",newPosition.toString());
			
			//refresh new position;
			if(PiecesModel.getInstance().selectedPiece.pieceVO.name.indexOf(PieceButton.NAME_PREFIX_RED)!=-1)
			{
				(PiecesModel.getInstance().redPiecesCollection.getItemAt(PiecesModel.getInstance().redPiecesCollection.getItemIndex(target)) as PieceButton).pieceVO.position = newPosition;
			}else
			{
				(PiecesModel.getInstance().bluePiecesCollection.getItemAt(PiecesModel.getInstance().bluePiecesCollection.getItemIndex(target)) as PieceButton).pieceVO.position = newPosition;
			}
			//refresh gamePosition
			BoardModel.getInstance().gamePosition.sett(newPosition[0],newPosition[1],target);
			log.debug("after arrived@tryMovement:{0}",BoardModel.getInstance().gamePosition.dump());
			//refresh gameGrid
			
			//refresh gameGraph
			var aGBnodeIndex:int = PositionTransactUtil.transactArray2Index(newPosition);
			var aLeftGB:GasketButton = BoardModel.getInstance().gasketsPosition.gett(newPosition[0]-1,newPosition[1]) as GasketButton;
			var aTopGB:GasketButton = BoardModel.getInstance().gasketsPosition.gett(newPosition[0],newPosition[1]-1) as GasketButton;
			var aRightGB:GasketButton = BoardModel.getInstance().gasketsPosition.gett(newPosition[0]+1,newPosition[1]) as GasketButton;
			var aBottomGB:GasketButton = BoardModel.getInstance().gasketsPosition.gett(newPosition[0],newPosition[1]+1) as GasketButton;
			log.debug("current aGBnodeIndex@tryMovement:{0}",aGBnodeIndex);
			log.debug("current aLeftGB@tryMovement:{0}",aLeftGB);
			log.debug("current aTopGB@tryMovement:{0}",aTopGB);
			log.debug("current aRightGB@tryMovement:{0}",aRightGB);
			log.debug("current aBottomGB@tryMovement:{0}",aBottomGB);
			//reset graphNode;
			BoardModel.getInstance().gameGraph.removeNode( aGBnodeIndex );
			BoardModel.getInstance().gameGraph.addNode( new Node( aGBnodeIndex ));
			//refresh graphEdge;
			//left
			if( aLeftGB is GasketButton)
			{
				BoardModel.getInstance().gameGraph.removeEdge( PositionTransactUtil.transactArray2Index(aLeftGB.position),aGBnodeIndex );
				if( BoardModel.getInstance().gamePosition.gett(aLeftGB.position[0],aLeftGB.position[1])==null )
				{
					BoardModel.getInstance().gameGraph.addEdge( new WeightedEdge( 
																					aGBnodeIndex,
																					PositionTransactUtil.transactArray2Index(aLeftGB.position),
																					1
																				)
														   );
				}
			}
			//top
			if( aTopGB is GasketButton)
			{
				BoardModel.getInstance().gameGraph.removeEdge( PositionTransactUtil.transactArray2Index(aTopGB.position),aGBnodeIndex );
				if( BoardModel.getInstance().gamePosition.gett(aTopGB.position[0],aTopGB.position[1])==null )
				{
					BoardModel.getInstance().gameGraph.addEdge( new WeightedEdge( 
																					aGBnodeIndex,
																					PositionTransactUtil.transactArray2Index(aTopGB.position),
																					1
																				)
														   );
				}
			}
			//right
			if( aRightGB is GasketButton)
			{
				BoardModel.getInstance().gameGraph.removeEdge( PositionTransactUtil.transactArray2Index(aRightGB.position),aGBnodeIndex );
				if( BoardModel.getInstance().gamePosition.gett(aRightGB.position[0],aRightGB.position[1])==null )
				{
					BoardModel.getInstance().gameGraph.addEdge( new WeightedEdge( 
																					aGBnodeIndex,
																					PositionTransactUtil.transactArray2Index(aRightGB.position),
																					1
																				)
														   );
				}
			}
			//bottom
			if( aBottomGB is GasketButton)
			{
				BoardModel.getInstance().gameGraph.removeEdge( PositionTransactUtil.transactArray2Index(aBottomGB.position),aGBnodeIndex );
				if( BoardModel.getInstance().gamePosition.gett(aBottomGB.position[0],aBottomGB.position[1])==null )
				{
					BoardModel.getInstance().gameGraph.addEdge( new WeightedEdge( 
																					aGBnodeIndex,
																					PositionTransactUtil.transactArray2Index(aBottomGB.position),
																					1
																				)
														   );
				}
			}	
			log.debug("afterMovement gameGraph status:{0}",DebugUtil.dumpGameGraph());	
			log.info("~tryMovement()");										
			//repopluate game board;
			BoardManager.repopulation();
			//calculateResult:
			calculateResult(BoardModel.getInstance().gamePosition);
			
			return true;
		}
		/**
		 * 
		 * @param calculate gamePositon's result
		 * 
		 */		
		private static function calculateResult(gamePositon:Array2):void
		{
			if(!PlayerManager.analysisGame(PiecesModel.getInstance().redPiecesCollection,PiecesModel.getInstance().bluePiecesCollection))
			{
				if(PlayerModel.getInstance().gameTurnStatus==PlayerModel.getInstance().IS_BLUE_TURN_NOW)
				{
					PlayerManager.isComputerTurnNow();
				}else
				{
					PlayerManager.isHumanTurnNow();	
				}
			}
		}	
		
		
	}
}